class Activity(object):
    def __init__(self, pgm, sAct, aSubjects, nTime, sId, bCopySegment=False):
        self.pgm = pgm;
        self.nTime = nTime; #REMOVE Later (used only for making Rnd Graphs [but can be used as id="endT.sId"])
        self.sActivity = sAct;
        self.aSubjects = aSubjects;
        self.sId = sId;
        self.aChildNodes = [];
        self.nLikelihood = 0;
        self.nProb_ObsNull = 0.01; #Change 0.1 to Null Prob Model: P(Ch|~M)  
        self.rootAct = "None";
        self.bCopySegment = bCopySegment;
    
    def makeXmlGraph(self, graph, nPrior):
        graph.addnode(self.rootAct, [], [nPrior]); #self.rootAct.aScores);
        
    def addChilds(self, graph):
        for childNode in self.aChildNodes:
            if int(childNode.aTimes[-1].replace("+",""))!=self.nTime:
                continue;
            aParents, aCondProbs = [], [];
            for parentId in childNode.sParentsId:   
                aParents.append(graph.idndict[parentId]);
                aCondProbs.extend(self.rootAct.aScores);
            aCPT = [self.nProb_ObsNull, self.rootAct.aScores[0]]; #TEMPORAL (only the main Likelihood)
#             print "%^:", childNode.name, aCPT;
            graph.addnode(childNode, aParents, aCPT);
            break; #TEMPORAL (only one Obs Node)
    
    def makeXmlNode(self, sId, sActName, aLatestActors, aActorsInfo, aTimes, nRealInitT, 
                    sParentsId, aScores, sLocation, bRoot):
        sName = self.getNodeName(sId, sActName, aTimes, aLatestActors);
        node = self.pgm.Node(sName, sId=sId, actName=sActName, aSubjects=aLatestActors, 
                              timeId=self.nTime, aTimes=aTimes, aScores=aScores, 
                              aActorsInfo=aActorsInfo, nRealInitT=nRealInitT,
                              location=sLocation, sParentsId=sParentsId);
        if bRoot: 
            self.rootAct = node;
            self.nLikelihood = aScores[0];
        else:
            self.aChildNodes.append(node);
            
    def removeAct(self, graph):
        graph.removeNode(self.rootAct);
        for childNode in self.aChildNodes:
            graph.removeNode(childNode); 
    
    def changeInitT(self, nNewInitT):
        self.rootAct.aTimes[0] = str(nNewInitT);
        self.rootAct.name = self.getNodeName(self.sId, self.sActivity, 
                                             self.rootAct.aTimes, self.aSubjects);
        
    def getNodeName(self, sId, sActName, aTimes, aSubjects):
        sSubjects = "(" + ", ".join(aSubjects) + ")";
        sTimes = "[" + "-".join(aTimes) + "]";
        return sId+"-"+sActName+"\\n"+sSubjects+"\\n"+sTimes;
        
    def getKeyTexts(self):
        return [[self.sActivity], self.aSubjects];    
            
    def getCPT(self, aCondProbs, aActs):
        aCPT = [];
        nSize = len(aCondProbs);
        for i in range(2**nSize):
            sBinCPT = bin(i)[2:].zfill(nSize); #Get each Binary Number combination
            nProb = 0;
            if not(self.getMEx(sBinCPT, aActs)): #Check if there is Mutual Exclusivity
                #Compute Independence Prob (for this entry in CPT)
                nIndActs, nProb = 0, 1;
                aIndActs = [];
                for j, sVal in enumerate(sBinCPT):
                    if sVal=="1":
                        nProb *= aCondProbs[j];
                        nIndActs += 1;
                        aIndActs.append(j);
#                 if len(aIndActs)>1:
#                     for iAct in aIndActs:
#                         print "Independent Act:", aActs[iAct].name;
#                     print "---";
                if nIndActs==0:
                    nProb = self.nProb_ObsNull; #Prob(Obs|Nothing True)
            aCPT.append(nProb);
        return aCPT;
    
    def getMEx(self, sBinCPT, aActs):
        if sBinCPT.count("1")<2:
            return False;
        #Get All Acts whose CPT entry shows as True
        aActsTrue = [];
        for i, sVal in enumerate(sBinCPT):
#             if sVal=="1" and aActs[i].actName=="Null": #If there are 2 or more True Nodes & one of them is Null, then MEx=True
#                 return True;
            if sVal=="1":
                aActsTrue.append(aActs[i]);
        for actM1 in aActsTrue:
            for actM2 in aActsTrue:
                if actM1!=actM2:
                    for sArg in actM1.aSubjects:
                        if sArg in actM2.aSubjects:
                            return True;
        return False;
            